package vn.fpt.snake.controller;

import java.awt.Image;
import java.awt.Point;
import java.util.List;

import vn.fpt.snake.commons.Constants;
import vn.fpt.snake.commons.Direction;
import vn.fpt.snake.commons.Utility;
import vn.fpt.snake.entity.AbstractFruit;
import vn.fpt.snake.entity.Settings;
import vn.fpt.snake.entity.Snake;
import vn.fpt.snake.view.Board;

public class SnakeControllerImpl extends AbstractController {
	Board parent;
	Utility utility;
	GameControllerImpl gameController;

	public SnakeControllerImpl(Board parent) {
		super();
		this.parent = parent;
		gameController = new GameControllerImpl();
		utility = new Utility();
	}

	// Create new snake
	public Snake createNewSnake() throws Exception{
		Settings settings = dataAccess.getSettings();
		int sizeOfArray = settings.getSizeOfArray();
		int dots = settings.getDots();
		int dotSize = settings.getDotSize();
		Point startPoint = utility.randomPoint();
		Image dot = gameController.getImage(Constants.DOT_IMG);
		Image head = gameController.getImage(Constants.HEAD_IMG);
		// Testing here
		Snake snake = new Snake(sizeOfArray);
		snake.setDots(dots);
		snake.setScore(0);
		snake.setStartPoint(startPoint);
		snake.setDot(dot);
		snake.setHead(head);
		snake.setRotate(0);

		for (int i = 0; i < dots; i++) {
			snake.setX(i, startPoint.x - dotSize * i);
			snake.setY(i, startPoint.y);
		}
		return snake;
	}

	// Return snake at next step
	public Snake move(Snake snake, Direction direction) {
		if (snake != null) {
			Settings settings = dataAccess.getSettings();
			int dotSize = settings.getDotSize();
			int width = settings.getWidth();
			int height = settings.getHeight();
			// Shift body up...
			for (int i = snake.getDots(); i > 0; i--) {
				int previousX = snake.getX(i - 1);
				int previousY = snake.getY(i - 1);
				snake.setX(i, previousX);
				snake.setY(i, previousY);
			}

			// .. and setting head
			int x = snake.getX(0);
			int y = snake.getY(0);
			
			if (direction == Direction.left) {
				int newX = x - dotSize;
				if (newX < 0)
					newX = width;
				snake.setX(0, newX);
			}

			if (direction == Direction.right) {
				int newX = x + dotSize;
				if (newX > width)
					newX = 0;
				snake.setX(0, newX);
			}

			if (direction == Direction.up) {
				int newY = y - dotSize;
				if (newY < 0)
					newY = height;
				snake.setY(0, newY);
			}

			if (direction == Direction.down) {
				int newY = y + dotSize;
				if (newY > height)
					newY = 0;
				snake.setY(0, newY);
			}
			return snake;
		}
		return null;
	}

	// Check snake hit itself
	public void checkCollision(Snake snake) throws Exception{
		if (snake != null) {
			for (int i = 1; i < snake.getDots(); i++) {
				if (snake.getX(i) == snake.getX(0)
						&& snake.getY(i) == snake.getY(0)) {
					gameController.switchGameOverView(parent, snake.getScore());
					break;
				}
			}
		}
	}

	// Check snake eat fruit ?
	// Return true when eat apple
	public boolean eatFruit(Snake snake, List<AbstractFruit> fruits) throws Exception {
		boolean isEatApple = false;
		if (snake != null && fruits != null) {
			int score = snake.getScore();
			Point headSnake = new Point(snake.getX(0), snake.getY(0));
			for (AbstractFruit fruit : fruits) {
				if (fruit.getX() == headSnake.getX()
						&& fruit.getY() == headSnake.getY()) {
					Point newPoint = new Point();
					if (fruit.isDie()) {
						gameController.switchGameOverView(parent, snake.getScore());
					} else if (fruit.getDot() > 0) {
						newPoint = utility.randomPoint();
						isEatApple = true;
					} else if (fruit.getDot() == 0) {
						newPoint = new Point(-1, -1);
						fruit.setIcon(null);
					}
					fruit.setX(newPoint.x);
					fruit.setY(newPoint.y);
					snake.setScore(score + fruit.getScore());
				}
			}
		}
		return isEatApple;
	}
}
